package com.jz.socket;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

/**
 * UDP客户端程序，用于对服务端发�?�数据，并接收服务端的回应信�?.
 */
abstract public class UDPSocketClient {
    public static final Logger LOGGER = LoggerFactory.getLogger(UDPSocketClient.class);
    private byte[] buffer = new byte[1024];

    private DatagramSocket ds = null;

    public static String UDP_HOST = "127.0.0.1";
    //UDP广播端口
    public static int UDP_PORT = 3344;
    public static int SEND_INTERVAL = 5;


    /**
     * 构�?�函数，创建UDP客户�?
     *
     * @throws Exception
     */
    public UDPSocketClient(String host,int port,int interval) throws Exception{
        this.UDP_HOST = host;
        this.UDP_PORT = port;
        this.SEND_INTERVAL = interval;
        init();
    }

    private void init(){
        try {
            ds = new DatagramSocket();
            new Thread(new Runnable() {
                public void run() {
                    try {
                        while (true) {
                            Thread.sleep(SEND_INTERVAL * 1000);
                            send();
                        }
                    } catch (Exception e) {
                        LOGGER.error("UDP发�?�信息异�?", e);
                    }
                }
            }).start();
        } catch (Exception e) {
            LOGGER.error("UPD CLIENT初始化失�?", e);
        }
    }

    /**
     * 设置超时时间，该方法必须在bind方法之后使用.
     *
     * @param timeout 超时时间
     * @throws Exception
     */
    public final void setSoTimeout(final int timeout) throws Exception {
        ds.setSoTimeout(timeout);
    }

    /**
     * 获得超时时间.
     *
     * @return 返回超时时间
     * @throws Exception
     */
    public final int getSoTimeout() throws Exception {
        return ds.getSoTimeout();
    }

    public final DatagramSocket getSocket() {
        return ds;
    }

    /**
     * 向指定的服务端发送数据信�?.
     *
     * @param host  服务器主机地�?
     * @param port  服务端端�?
     * @param bytes 发�?�的数据信息
     * @return 返回构�?�后俄数据报
     * @throws IOException
     */
    public final DatagramPacket send(final String host, final int port,
                                     final byte[] bytes) throws IOException {
        DatagramPacket dp = new DatagramPacket(bytes, bytes.length, InetAddress
                .getByName(host), port);
        ds.send(dp);
        return dp;
    }

    /**
     * 向指定的服务端发送数据信�?.
     *
     * @param String 发�?�的数据信息
     * @return 返回构�?�后俄数据报
     * @throws IOException
     */
    public final DatagramPacket send() {
//        byte[] pm = CuratorSupport.getLocalAppNodeValue();
        byte[] pm = getPushValue();
        if(pm == null){
            pm = "APP_NODE节点数据无效".getBytes();
        }
        DatagramPacket dp = null;
        try {
            LOGGER.info(new String(pm));
            dp = new DatagramPacket(pm, pm.length, InetAddress
                    .getByName(UDP_HOST), UDP_PORT);
            ds.send(dp);
        } catch (Exception e) {
            LOGGER.error("UPD发�?�失�?", e);
        }
        return dp;
    }

    /**
     * 接收从指定的服务端发回的数据.
     *
     * @return 返回从指定的服务端发回的数据.
     * @throws Exception
     */
    public final String receive()
            throws Exception {
        DatagramPacket dp = new DatagramPacket(buffer, buffer.length);
        ds.receive(dp);
        String info = new String(dp.getData(), 0, dp.getLength());
        return info;
    }

    /**
     * 关闭udp连接.
     */
    public final void close() {
        try {
            ds.close();
        } catch (Exception ex) {
            ex.printStackTrace();
            LOGGER.error("UPD广播程序异常",ex);
        }
    }

    abstract public byte[] getPushValue();
}
